package gui;

import engine.Attribute;
import generics.AbstractGroup;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

/**
 * This class is a panel that lets you select which group to manipulate and
 * updates sliders in the panel to reflect changeable attributes of the group
 * and current values of those attributes.
 * 
 * @author jianweigan
 * 
 */

@SuppressWarnings("serial")
public class SettingsPanel extends JPanel {

	public static final Dimension PANEL_SIZE = new Dimension(230, 600);
	public static final Dimension SCROLL_PANE_SIZE = new Dimension(200, 580);

	private GroupChooser myGroupChooser;
	private Canvas myDisplay;
	private JPanel mySlidersPanel;

	/**
	 * Meant to be constructed when the GUI is fired up. Contains an empty
	 * JComboBox since no groups are on the screen yet. and an empty JScrollPane
	 * to hold the sliders panel.
	 */
	public SettingsPanel(Canvas display) {
		myGroupChooser = new GroupChooser(ResourceStrings
				.getString("ChooserLabel"));
		myDisplay = display;
		mySlidersPanel = new JPanel();
		mySlidersPanel.setLayout(new BoxLayout(mySlidersPanel,
				BoxLayout.PAGE_AXIS));
		JScrollPane scrollPane = new JScrollPane(mySlidersPanel);
		scrollPane.setPreferredSize(SCROLL_PANE_SIZE);

		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); // vertical
																// layout
		setPreferredSize(PANEL_SIZE);
		add(Box.createGlue());
		add(myGroupChooser);
		add(scrollPane);
		repaint(100);
	}

	/**
	 * Changes the sliders based on the AbstractGroup selected. Clears all the
	 * sliders, and reconstructs sliders using the AbstractGroup's list of
	 * Attributes so that the current groups sliders are on display, and each
	 * group can have its own slider set which will be instantiated
	 * automatically.
	 */
	public void updateSliders(AbstractGroup group) {
		mySlidersPanel.removeAll();
		mySlidersPanel.setLayout(new BoxLayout(mySlidersPanel,
				BoxLayout.PAGE_AXIS));
		if (group != null) {
			for (Attribute attr : group.getAttributeList()) {
				mySlidersPanel.add(new AttributeSlider(attr));
			}
		}
		// need to call validate once you remove/add items
		mySlidersPanel.validate();
	}

	/**
	 * Clears JComboBox's groups and all sliders
	 */
	public void clearGroups() {
		myGroupChooser.removeAllItems();
		myGroupChooser.validate();

		mySlidersPanel.removeAll();
		mySlidersPanel.validate();
	}

	/**
	 * Attempts to add an object to the group chooser in the settings panel.
	 * Only adds the object if it is a Group. Added item also shown as selected
	 * item in chooser.
	 * 
	 * @param obj
	 *            Group to be added
	 */
	public void addChoosable(Object obj) {
		if (obj instanceof AbstractGroup) {
			myGroupChooser.addGroupAndFocus((AbstractGroup) obj);
		}
	}

	/**
	 * Removes currently selected group in group choooser
	 */
	public void removeCurrentGroup() {
		myGroupChooser.removeCurrent();
	}

	/**
	 * This class implements a JComboBox (drop down menu) that lets you choose a
	 * Group to modify.
	 * 
	 * Created as an inner class to access variables of settings panel class.
	 * 
	 * @author jianweigan
	 * 
	 */
	public class GroupChooser extends JComboBox implements ActionListener {

		public final Dimension CHOOSER_SIZE = new Dimension(200, 90);

		/**
		 * Constructs a ComboBox
		 * 
		 * @param title
		 */
		public GroupChooser(String title) {
			super();
			super.setPreferredSize(CHOOSER_SIZE);
			setBorder(BorderFactory.createTitledBorder(BorderFactory
					.createEtchedBorder(), title));
			addActionListener(this);
		}

		/**
		 * Adds a new item to the ComboBox and sets it as the currently selected
		 * item in the chooser.
		 * 
		 * @param newbie
		 *            Group to be added
		 */
		public void addGroupAndFocus(AbstractGroup newbie) {
			addItem(newbie);
			setSelectedItem(newbie);
		}

		/**
		 * Called when new item selected in the menu, also when addGroupAndFocus
		 * is called i.e. a new group added to this box. Updates settings'
		 * display i.e. sliders and slider values to reflect Behavior values
		 * from group
		 */
		public void actionPerformed(ActionEvent e) {
			SettingsPanel.this.updateSliders(getSelectedGroup());
		}

		/**
		 * Removes currently selected item from chooser then chooses previous
		 * item, or next item, or none if no more items in chooser.
		 */
		public void removeCurrent() {
			int index = getSelectedIndex();
			AbstractGroup selected = getSelectedGroup();
			if (getItemCount() > 0) { // check for empty chooser
				removeItemAt(index);
				myDisplay.removeGroup(selected);
				if (getSelectedItem() == null) {
					mySlidersPanel.removeAll();
					mySlidersPanel.validate();
				}
			}
		}

		/**
		 * Checks if the selected item is an AbstractGroup
		 * 
		 * @return selected group in chooser or null if selected is not a group
		 *         or nothing in chooser
		 */
		public AbstractGroup getSelectedGroup() {
			if (getSelectedItem() instanceof AbstractGroup)
				return (AbstractGroup) getSelectedItem();
			else
				return null;
		}
	}

}
